Shell 脚本编程 —— 秘笈1
<!-- toc -->
<!-- tocstop -->
shell脚本编程的特点
简单、快速以及轻松
第一个shell脚本编程
为了能成功编写有一个shell脚本,需要做三件事情
- 写一个脚本
- 赋予脚本可执行权限
- 把脚本放在shell可以找到的某个地方
如下是一个文件,文件名hello_world
1
2
3
4
# 第一行#!是声明指令,来调用这个脚本的shell来检测
# My first script
echo "hello world!"
1. 编程的基本要素
1.1 变量
变量是通过名字能访问到的存储信息的内存。
与大多数解释型语言相同,shell编程中变量无需事先声明。shell对变量是一视同仁的,只要看到以 $ 开始的单词,它就去寻找变量的值然后替换它。
变量名的命名必须遵循以下规则:
- 首个字符必须为字母(a-z,A-Z)
- 中间不能有空格,可以使用下划线(_)
- 不能使用标点符号
- 不能使用bash里的关键字(可用help命令查看保留关键字)
1.2 运算
只提供了整数的数学运算,并且不检测溢出。和其他语言一样,对除法运算的要求是除数不能为0,也可以捕获到除以零的情况并报错。
1
2
3weight=1
weight=$weight+1
echo $weight
打印出来的结果不是2而是1+1。为了达到我们的预期效果,有以下集中表达方式可供参考(基本的运算除了有加减乘除+-*/,还有取余运算):
- expr用于整数值运算,每一项用空格隔开
1
2 > weight=`expr $weight + 1`
>
注意“+”号两边的空格,否则还是按照字符串的方式赋值。“`”符号与$(命令)的语法等效,用于获取命令的stdout中的内容。expr实际上是一个命令,表达式计算结果输出到stdout中。做乘法时需要注意,因为“*”在shell中有特殊意义,所以应该写成“\*”或者用引号“"*"”括起来。另外,`命令`是一种古老的表示方法,用$(命令)更好。
- let 表示数学运算
let "weight+=1"
或let "weight=$weight+1"
- (())方式与let类型
((weight+=1))
或((weight=$weight+1))
- $[]将中括号内的表达式作为数学运算先计算结果再输出
weight=$[$weight+1]
1.3 流程控制
脚本程序包含了一系列的命令,一行一行地开始执行直到最后结束。但是大多数程序的结构不止如此,还有比较复杂的逻辑,会根据不同情况(条件)进行不同的动作。通过使用shell提供的 if 、 exit 、 for 、 while 、 until 、 case 、 break 、 continue 这些关键字我们可以控制执行的顺序。
1. if 语句
if 命令有三种形式
- 第一种
1
2
3
4
5 > #条件为真执行;条件为假不做任何事情
> if condition ; then
> commands
> fi
>
- 第二种
1
2
3
4
5
6
7 > #条件为真执行command1;条件为假执行command2
> if condition ; then
> command1
> else
> command2
> fi
>
- 第三种
1
2
3
4
5
6
7 > #条件1为真执行command1;条件2为真时执行command2
> if condition1 ; then
> command1
> elif condition2 ; then
> command2
> fi
>
2. test 语句
一个正确编写的Unix应用程序会告诉操作系统执行地成功与否。它用什么方法告诉系统呢?那就是我们经常用到的exit状态。exit的状态数值的范围为0~255。“0”表示成功,其他数值都表示失败。exit状态有两个很重要的功能。第一个作用是检测和处理错误,第二个作用是可以执行 true/false 测试。 这种 true/false 的判断经常时通过test和if一起配合实现的,可以有两种语法形式:
- 第一种形式
test expression
- 第二种形式 (注意:“[”、“]”和expression 之间必须有空格)
[ expression ]
test 命令工作很简单。如果给定的表达式为true,test退出的状态值为0,否则退出的状态值为1。
test 命令可以判断3类条件:
- 数值比较
- -eq [ n1 -eq n2 ] 检查n1是否与n2相等
- -ge [ n1 -ge n2 ] 检查n1是否大于或等于n2
- -gt [ n1 -gt n2 ] 检查n1是否大于n2
- -le [ n1 -le n2 ] 检查n1是否小于或等于n2
- -lt [ n1 -lt n2 ] 检查n1是否小于n2
- -ne [ n1 -ne n2 ] 检查n1是否不等于n2
- 字符串比较
- = [ str1 = str2 ] 检查str1是否和str2相同
- != [ str1 != str2 ] 检查str1是否和str2不同
- < [ str1 < str2 ] 检查str1是否比str2小
- > [ str1 > str2 ] 检查str1是否比str2大
- -n [ -n str1 ] 检查str1的长度是否非0
- -z [ -z str1 ] 检查str1的长度是否为0
- 文件比较
- -d [ -d file ] 检查file是否存在并且是一个目录
- -e [ -e file ] 检查file是否存在
- -f [ -f file ] 检查file是否存在并且是一个文件
- -r [ -r file ] 检查file是否存在并且可读
- -s [ -s file ] 检查file是否存在并且非空
- -w [ -w file ] 检查file是否存在并且可写
- -x [ -x file ] 检查file是否存在并且可执行
- -O [ -O file ] 检查file是否存在并且属当前用户所有
- -G [ -G file ] 检查file是否存在并且默认组与当前用户相同
- -nt [ file1 -nt file2 ] 检查file1是否比file2新
- -ot [ file1 -ot file2 ] 检查file1是否比file2旧
3. exit 语句
一个好的脚本编程者应该在脚本完成时设置 exit 状态。为了实现这个要求,就要使用 exit 命令。exit命令使脚本带着状态值立刻退出。例如:
1
2exit 0 # 退出脚本,状态值为0 (成功)
exit 1 # 退出脚本,状态值为1 (失败)
4. case 语句
case表达式可以用来匹配一个给定的字符串,而不是数字。case语句有以下格式:
1
2
3case word in
模式) 声明 ;;
esac
1
2
3
4
5
6case $1 in
-h) help; shift 1;; #调用help函数
--) shift; break;; #结束选项
-*) error "error: no such option $1. -h for help";; # 错误提示
*) break;; #退出判断
esac
上面使用了一个特殊变量$1,该变量包含有传递给这个脚本的第一个参数值。“*”意味着匹配任何东西。在最后的模式匹配中加入*这项是个好习惯,可以用它来检测非法的输入。
5. for/while 循环语句
循环是只要条件成立就反复执行。shell有两种形式的循环,一种是while(until),另一种是for。
1
2
3while ... ; do
...
done
只要测试表达式条件为真,则while循环将一直运行。关键字“break”用来跳出循环,而关键字“continue”则可以跳过一个循环的余下部分,直接跳到下一次循环中。
for循环会查看一个字符串行表(字符串用空格分隔),若找到匹配进行循环:
1
2
3for var in ... ; do
...
done